package org.example.liangchenbackend.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.example.liangchenbackend.annotation.AuthCheck;
import org.example.liangchenbackend.common.BaseResponse;
import org.example.liangchenbackend.common.DeleteRequest;
import org.example.liangchenbackend.common.ResultUtils;
import org.example.liangchenbackend.constant.UserConstant;
import org.example.liangchenbackend.exception.BusinessException;
import org.example.liangchenbackend.exception.ErrorCode;
import org.example.liangchenbackend.exception.ThrowUtils;
import org.example.liangchenbackend.model.dto.user.UserLoginRequest;
import org.example.liangchenbackend.model.dto.user.UserQueryRequest;
import org.example.liangchenbackend.model.dto.user.UserRegisterRequest;
import org.example.liangchenbackend.model.dto.user.UserUpdateRequest;
import org.example.liangchenbackend.model.entity.User;
import org.example.liangchenbackend.model.vo.LoginUserVO;
import org.example.liangchenbackend.model.vo.UserVO;
import org.example.liangchenbackend.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 本地缓存（存储验证码相关信息）
     */
    private final Cache<String, String> LOCAL_CACHE = Caffeine.newBuilder()
            .initialCapacity(1024)
            .maximumSize(1) // 最大 1 条
            // 缓存 5 分钟后移除
            .expireAfterWrite(Duration.ofMinutes(5))
            .build();

    /**
     * 用户注册
     */
    @PostMapping("/register")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        ThrowUtils.throwIf(userRegisterRequest == null, ErrorCode.PARAMS_ERROR);
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        long result = userService.userRegister(userAccount, userPassword, checkPassword);
        return ResultUtils.success(result);
    }

    /**
     * 用户登录
     */
    @PostMapping("/login")
    public BaseResponse<LoginUserVO> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(userLoginRequest == null, ErrorCode.PARAMS_ERROR);
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        //获取用户输入的验证码
        String captcha = userLoginRequest.getCaptcha();
        //获取真实的验证码
//        String code = (String) request.getSession().getAttribute("code");
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        String code = opsForValue.get("code");

        code =  LOCAL_CACHE.getIfPresent("code");
        System.out.println("captcha = " + captcha);
        System.out.println("code = " + code);
        //校验验证码,验证码错误的时候就不需要校验账号密码，减少查库，节约资源
        if ( !code.equalsIgnoreCase(captcha) )
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码错误");

        LoginUserVO loginUserVO = userService.userLogin(userAccount, userPassword, request);
        return ResultUtils.success(loginUserVO);
    }

    /**
     * 获取当前登录用户
     */
    @GetMapping("/get/login")
    public BaseResponse<LoginUserVO> getLoginUser(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        return ResultUtils.success(userService.getLoginUserVO(loginUser));
    }

    @PostMapping("/logout")
    public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
        boolean result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    /**
     * 删除用户
     */
    @PostMapping("/delete")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> deleteUser(@RequestBody DeleteRequest deleteRequest) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        boolean b = userService.removeById(deleteRequest.getId());
        return ResultUtils.success(b);
    }

    /**
     * 分页获取用户封装列表（仅管理员）
     *
     * @param userQueryRequest 查询请求参数
     */
    @PostMapping("/list/page/vo")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<UserVO>> listUserVOByPage(@RequestBody UserQueryRequest userQueryRequest) {
        ThrowUtils.throwIf(userQueryRequest == null, ErrorCode.PARAMS_ERROR);
        long current = userQueryRequest.getCurrent();
        long pageSize = userQueryRequest.getPageSize();
        Page<User> userPage = userService.page(new Page<>(current, pageSize),
                userService.getQueryWrapper(userQueryRequest));
        Page<UserVO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserVO> userVOList = userService.getUserVOList(userPage.getRecords());
        userVOPage.setRecords(userVOList);
        return ResultUtils.success(userVOPage);
    }

    /**
     * hutool库登录注册验证码
     */
//    @GetMapping("/getCaptcha")
//    public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
//        // 设置请求头为输出图片类型
//        response.setContentType("image/png");
//        //禁止图像缓存。
//        response.setHeader("Pragma", "no-cache");
//        response.setHeader("Cache-Control", "no-cache");
//        response.setDateHeader("Expires", 0);
//        // 生成验证码，将结果放入session
//        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
//        session.setAttribute("code", lineCaptcha.getCode());
//        // 输出验证码图片流
//        lineCaptcha.write(response.getOutputStream());
//    }


    @GetMapping("/getCaptcha")
    public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
        // 设置请求头为输出图片类型
        response.setContentType("image/png");
        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        // 生成4位纯数字验证码
        String code = RandomUtil.randomNumbers(4);

        // 创建验证码图片
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);

        // 自定义 CodeGenerator 实现
        CodeGenerator codeGenerator = new CodeGenerator() {
            @Override
            public String generate() {
                return code; // 返回生成的验证码
            }

            @Override
            public boolean verify(String code, String userInputCode) {
                return code.equalsIgnoreCase(userInputCode); // 验证用户输入的验证码
            }
        };

        lineCaptcha.setGenerator(codeGenerator); // 设置自定义的验证码生成器

        // 将验证码结果放入session
//        session.setAttribute("code", code);
        //这种放到session操作，火狐浏览器正常，但是edge浏览器会报错，所以改为放到redis中
//        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
//        opsForValue.set("code", code, 600, TimeUnit.SECONDS);

        //本地缓存存储验证码信息
        LOCAL_CACHE.put("code", code);

        // 输出验证码图片流
        lineCaptcha.write(response.getOutputStream());
    }

    /**
     * 修改个人资料
     * 现在只让管理员修改资料
     * @RequestBody User user
     * @return
     */
    @PostMapping("/updateUserInfo")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> updateUser(@RequestBody UserUpdateRequest userUpdateRequest) {
        if (userUpdateRequest == null || userUpdateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = new User();
        BeanUtils.copyProperties(userUpdateRequest, user);
        boolean result = userService.updateById(user);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(true);
    }

}
